package cn.hicard.auth.dao.impl;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Repository;

import cn.hicard.auth.dao.BaseDao;
import cn.hicard.auth.dao.SourceDao;
import cn.hicard.auth.entity.MgSource;
import cn.hicard.auth.web.Node;

/**
 * 资源管理DAO接口实现
 * @author zhangy
 *
 */
@Repository
public class SourceDaoImpl extends BaseDao<MgSource> implements SourceDao {
		
	@Override
	public Node findNodeByType(int rootPk, String type) throws Exception{
		Node node = null;
		// 起始节点
		MgSource source = getOne(rootPk);
		if(source != null){
			node = new Node();
			node.setPk(rootPk);
			node.setName(source.getSourcename());
			node.setControlid(source.getControlid());
			// 类型资源
			node.setChildren(findNodeListByType(node, type));	
		}		
		return node;
	}
	
	@Override
	public Node findNodeByRoles(int rootPk, List<Integer> roleids) throws Exception{
		Node node = null;
		MgSource source = getOne(rootPk); // 系统根资源主键
		if(source != null){
			node = new Node();
			node.setPk(rootPk);
			node.setName(source.getSourcename());
			node.setControlid(source.getControlid());
			node.setChildren(findNodeListByRoles(node, roleids));			
		}
		return node;
	}


	/**
	 * 递归: 根据父节点parent递归查询所有层级子节点
	 * @param parent上级节点
	 * @param type资源类型，当type为null时，则表示查询所有类型
	 * @return
	 * @throws Exception
	 */
	private List<Node> findNodeListByType(Node parent, String type) throws Exception{		
		List<Node> children = null;						
		// 查询资源
		String hql = "FROM MgSource WHERE parentid=?";
		List<MgSource> list;
		if(type != null && type.length() !=0){
			hql += " AND sourcetype=?";
			list = super.findByHql(hql, parent.getPk(), type);
		}else{
			list = super.findByHql(hql, parent.getPk());
		}		
		// 如果有子级资源
		if (list != null && list.size() > 0) {			
			children = new ArrayList<Node>();			
			for (MgSource rs : list) {
				Node child = new Node();
				child.setPk(rs.getPkSource());
				child.setName(rs.getSourcename());
				child.setControlid(rs.getControlid());
				child.setParent(parent);
				//@TODO child.setLevel(level);
				// ***** 递归点 ***** //
				child.setChildren(findNodeListByType(child, type));				
				children.add(child);				
			}
		}
		return children;
	}
	
	/**
	 * 递归: 根据父节点parent及指定的角色集合roleids，递归查询所有层级子节点
	 * @param parent
	 * @param roleids
	 * @return
	 * @throws Exception
	 */
	private List<Node> findNodeListByRoles(Node parent, List<Integer> roleids) throws Exception{
		
		List<Node> children = null;
		// 查询角色所拥有的资源HQL
		StringBuilder sb = new StringBuilder();
		sb.append("SELECT s ");
		sb.append("FROM MgSource s WHERE s.parentid=");
		sb.append(parent.getPk());
		sb.append(" AND ");
		sb.append("s.pkSource IN (");
		sb.append("SELECT DISTINCT rs.id.pkSource FROM MgRoleSource rs");
		if(roleids != null && roleids.size()>0){
			sb.append(" WHERE rs.id.pkRoleinfo IN(");
			for (int i=0; i<roleids.size(); i++) {
				sb.append(roleids.get(i));
				if(i<roleids.size()-1){
					sb.append(",");
				}
			}
			sb.append(")");
		}		
		sb.append(")");
		
		List<MgSource> list = super.findByHql(sb.toString());
		
		if (list != null && list.size() > 0) {			
			children = new ArrayList<Node>();			
			for (MgSource rs:list) {
				Node child = new Node();
				child.setPk(rs.getPkSource());
				child.setName(rs.getSourcename());
				child.setControlid(rs.getControlid());
				child.setParent(parent);
				//child.setLevel(level);
				// ***** 递归点 ***** //
				child.setChildren(findNodeListByRoles(child, roleids));				
				children.add(child);				
			}
		}
		return children;
	}
	@Override
	public void save(MgSource source) throws Exception {
		super.save(source);
	}
	@Override
	public void update(MgSource source) throws Exception {
		super.update(source);
	}
	@Override
	public void delete(int pkSource) throws Exception {
		// 实现在递归删除，删除以当前节点为父节点的所有子节点及其附属子节点
		String childrenHQL = "SELECT pkSource FROM MgSource WHERE parentid=?";

		@SuppressWarnings("unchecked")
		List<Integer> pks = super.findFieldsByHql(childrenHQL, pkSource);
		
		// 多条 删除时，数据通常较多，所以使用HQL直接删除，而不是先查再删
		String delCurrHQL = "DELETE FROM MgSource WHERE pkSource=?";
		for (Integer pk : pks) {
			// 递归
			delete(pk);
		}
		// 调用大容量更新
		super.updateByHqlBulk(delCurrHQL, pkSource);
	}
	@Override
	public MgSource getOne(int pkSource) throws Exception {
		return super.getByPk(pkSource);
	}	
	@Override
	public List<MgSource> findByParent(int pk) throws Exception {
		String hql = "FROM MgSource WHERE parentid=?";
		return super.findByHql(hql, pk);
	}

}
